/**
 * 舍入模式
 * @type {{DOWN: number, ROUND: number, UP: number}}
 * @description {{DOWN: 舍弃, ROUND: 四舍五入, UP: 进位}}
 */
const RoundingMode = {
  /**
   * 以保留2位小数为例
   *1.011 -> 1.02
   */
  UP: 1,
  /**
   * 以保留2位小数为例
   *1.055 -> 1.05 , 1.056 -> 1.06
   */
  ROUND: 2,
  /**
   * 以保留2位小数为例
   *1.019 -> 1.01
   */
  DOWN: 3
}

/**
 * 是否移除小数后边的0
 * @type {{Y: number, N: number}}
 */
const RemoveTailZerosMode = {
  /**
   * 以保留2位小数为例
   *1.10 -> 1.1 ，1.00 ->1
   */
  Y: 1,
  /**
   * 以保留2位小数为例
   *1.1 -> 1.10 ，1 ->1.00
   */
  N: 2
}

export { RoundingMode, RemoveTailZerosMode }

/**
 *自定义保留小数位
 *
 * @param num 目标数字
 * @param scale 精确位数
 * @param roundingMode 舍入模式
 * @param removeTailZerosMode 小数点后的0是否移除
 * @returns {number} 返回数字
 */
export function toDefinedFixed (num, scale, roundingMode = RoundingMode.UP, removeTailZerosMode = RemoveTailZerosMode.Y) {
  // 非数字返回0
  if (!isNumber(num)) {
    return 0
  }
  // 校验scale或设置默认值
  if (!isNumber(scale) || scale < 0) {
    scale = 0
  }
  // 校验roundingMode或设置默认值
  if (isNullOrUndefined(roundingMode) ||
    (roundingMode !== RoundingMode.UP &&
      roundingMode !== RoundingMode.DOWN &&
      roundingMode !== RoundingMode.ROUND)) {
    roundingMode = RoundingMode.UP
  }
  // 校验removeTailZerosMode或设置默认值
  if (isNullOrUndefined(removeTailZerosMode) ||
    (removeTailZerosMode !== RemoveTailZerosMode.Y &&
      removeTailZerosMode !== RemoveTailZerosMode.N)) {
    removeTailZerosMode = RemoveTailZerosMode.Y
  }

  // 计算结果
  const result = computeRoundNum(num, scale, roundingMode)
  // 移除末尾的0
  if (removeTailZerosMode === RemoveTailZerosMode.Y) {
    return parseFloat(result.toString())
  }
  return result
}

/**
 *保留位数
 * UP:{
 * eg1:
 *    x = 2017.0621
 *    scale = 2
 *    2017.0621 *1000 -> 2017062.1 -> 2017062 -> (2017062 -2 + 10) = 2017070 -> 2017.07
 * eg2:
 *    x = 2017.0601
 *    scale = 2
 *    2017.0601 *1000 -> 2017060.1 -> 2017060  -> 2017.06
 * }
 *
 * @param x 目标数字
 * @param scale 精确位数
 * @param roundingMode 小数点后的0是否移除
 * @returns {string} 返回小数
 */
function computeRoundNum (x, scale = 2, roundingMode = RoundingMode.ROUND) {
  // 四舍五入模式
  if (RoundingMode.ROUND === roundingMode) {
    return x.toFixed(scale)
  }
  // eg:scale=2 ,power =1000
  const power = Math.pow(10, (scale + 1))
  // 往下取整 eg:x=2017.0621 ,i =2017062
  const i = Math.floor(x * power)
  // eg:i =2017062, iStr="2017062"
  const iStr = i.toString()
  // eg:i =2017062, iStr="2017062" ,lastNum=2
  const lastNum = parseInt(iStr.charAt(iStr.length - 1))
  let result = 0
  // 向上进位
  if (RoundingMode.UP === roundingMode) {
    if (lastNum !== 0) {
      // (2017062-2)+10=2017070 ,2017070.toFixed(3)=2017.07
      result = ((i - lastNum + 10) / power).toFixed(scale)
    } else {
      result = (i / power).toFixed(scale)
    }
    return result
  } else if (RoundingMode.DOWN === roundingMode) {
    result = ((i - lastNum) / power).toFixed(scale)
    return result
  }

  return x.toFixed(scale)
}

/**
 * 判断是null 或者 undefined
 * @param x
 * @returns {boolean}
 */
export function isNullOrUndefined (x) {
  return x === null || x === undefined
}

/**
 * 判断是否是数字
 *
 * @param x
 * @returns {boolean}
 */
export function isNumber (x) {
  if (isNullOrUndefined(x)) {
    return false
  }
  // 非负浮点数
  const regPos = /^\d+(\.\d+)?$/
  // 负浮点数
  const regNegPos = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/
  return regPos.test(x) || regNegPos.test(x)
}
